package br.com.ngame.device;

import java.awt.BufferCapabilities;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.Frame;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.ImageCapabilities;
import java.awt.Point;
import java.awt.Transparency;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;

public class WindowedVideoDevice implements VideoDevice
{
	private BufferStrategy bufferStrategy = null;
	private GraphicsDevice device;
	private Frame gameWindow = null;
	private Graphics2D graphics = null;

	public WindowedVideoDevice(int width, int height)
	{
		GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
		device = env.getDefaultScreenDevice();
		GraphicsConfiguration gc = device.getDefaultConfiguration();
		gameWindow = new Frame(gc);
		gameWindow.setUndecorated(true);
		gameWindow.setIgnoreRepaint(true);
		gameWindow.setSize(width, height);
		Dimension screen = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
		gameWindow.setLocation(screen.width / 2 - gameWindow.getWidth() / 2, screen.height / 2 - gameWindow.getHeight() / 2);
		gameWindow.setVisible(true);
	}

	public int setup()
	{
		gameWindow.createBufferStrategy(2);
		bufferStrategy = gameWindow.getBufferStrategy();
		hideCursor();
		reportCapabilities(device);
		showModes(device);
		return RESULT_OK;
	}

	public int cleanup()
	{
		setFullScreen(false);
		gameWindow.dispose();
		return RESULT_OK;
	}

	public int getWidth()
	{
		return gameWindow.getWidth();
	}

	public int getHeight()
	{
		return gameWindow.getHeight();
	}

	public Graphics2D getGraphics()
	{
		if (graphics == null)
		{
			graphics = (Graphics2D) bufferStrategy.getDrawGraphics();
		}
		return graphics;
	}

	public Image getScreenImage()
	{
		return null;
	}

	public void update()
	{
		if (!bufferStrategy.contentsLost())
		{
			bufferStrategy.show();
		} else
		{
			System.out.println("* Video content lost.");
		}
		if (graphics != null)
		{
			graphics.dispose();
			graphics = null;
		}
	}

	public BufferedImage newImage(int width, int height)
	{
		return device.getDefaultConfiguration().createCompatibleImage(width, height, Transparency.BITMASK);
	}

	public BufferedImage cloneImage(Image img)
	{
		BufferedImage newImg = newImage(img.getWidth(null), img.getHeight(null));
		newImg.getGraphics().drawImage(img, 0, 0, null);
		return newImg;
	}

	private void reportCapabilities(GraphicsDevice device)
	{
		if (device != null)
		{
			GraphicsConfiguration gc = device.getDefaultConfiguration();
			//	 image capabilities
			ImageCapabilities imageCaps = gc.getImageCapabilities();
			System.out.println("Image Caps. isAccelerated: " + imageCaps.isAccelerated());
			System.out.println("Image Caps. isTrueVolatile: " + imageCaps.isTrueVolatile());
			//	 buffer capabilities
			BufferCapabilities bufferCaps = gc.getBufferCapabilities();
			System.out.println("Buffer Caps. isPageFlipping: " + bufferCaps.isPageFlipping());
			System.out.println("Buffer Caps. Flip Contents: " + getFlipText(bufferCaps.getFlipContents()));
			System.out.println("Buffer Caps. Full-screen Required: " + bufferCaps.isFullScreenRequired());
			System.out.println("Buffer Caps. MultiBuffers: " + bufferCaps.isMultiBufferAvailable());
		}
	}

	private String getFlipText(BufferCapabilities.FlipContents flip)
	{
		if (flip == null)
		{
			return "false";
		} else if (flip == BufferCapabilities.FlipContents.UNDEFINED)
		{
			return "Undefined";
		} else if (flip == BufferCapabilities.FlipContents.BACKGROUND)
		{
			return "Background";
		} else if (flip == BufferCapabilities.FlipContents.PRIOR)
		{
			return "Prior";
		} else // if (flip == BufferCapabilities.FlipContents.COPIED)
		{
			return "Copied";
		}
	}

	private void showModes(GraphicsDevice device)
	{
		DisplayMode[] modes = device.getDisplayModes();
		System.out.println("Avaible display modes:");
		for (int i = 0; i < modes.length; i++)
		{
			if (modes[i].getWidth() >= 640)
			{
				System.out.print("(" + modes[i].getWidth() + "," +
						modes[i].getHeight() + "," +
						modes[i].getBitDepth() + "," +
						modes[i].getRefreshRate() + ") ");
				if ((i + 1) % 4 == 0)
				{
					System.out.println();
				}
			}
		}
		System.out.println();
	}

	public boolean isFullScreenSupported()
	{
		return device.isFullScreenSupported();
	}

	public void setFullScreen(boolean value)
	{
		if (value)
		{
			if (device.isFullScreenSupported())
			{
				System.out.println("FULLSCREEN: " + gameWindow.getWidth() + "x" + gameWindow.getHeight());
				int w = gameWindow.getWidth();
				int h = gameWindow.getHeight();
				device.setFullScreenWindow(gameWindow);
				if (device.isDisplayChangeSupported())
				{
					device.setDisplayMode(new DisplayMode(w, h, 32, 60));
				}
			}
		} else
		{
			device.setFullScreenWindow(null);
		}
	}

	public boolean isFullScreen()
	{
		return device.getFullScreenWindow() != null;
	}

	protected void hideCursor()
	{
		ImageIcon emptyIcon = new ImageIcon(new byte[0]);
		Cursor invisibleCursor = gameWindow.getToolkit().createCustomCursor(emptyIcon.getImage(), new Point(0, 0), "Invisible");
		gameWindow.setCursor(invisibleCursor);
	}

	public Frame getFrame()
	{
		System.out.println("getFrame() = " + gameWindow);
		return gameWindow;
	}
}
